package com.wkbb.basic.utils;

import com.alibaba.fastjson.JSONObject;
import com.wkbb.common.constants.Constants;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.List;

/**
 * @author dengjingyuan
 * @date 2019-07-30 19:05
 */
@Slf4j
public class FileUtil {
    /**
     * 读取文件内容，作为字符串返回
     */
    public static String readFileAsString(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        }

        if (file.length() > 1024 * 1024 * 1024) {
            throw new IOException("File is too large");
        }

        StringBuilder sb = new StringBuilder((int) (file.length()));
        // 创建字节输入流
        FileInputStream fis = new FileInputStream(filePath);
        // 创建一个长度为10240的Buffer
        byte[] bbuf = new byte[10240];
        // 用于保存实际读取的字节数
        int hasRead = 0;
        while ((hasRead = fis.read(bbuf)) > 0) {
            sb.append(new String(bbuf, 0, hasRead));
        }
        fis.close();
        return sb.toString();
    }

    /**
     * 根据文件路径读取byte[] 数组
     */
    public static byte[] readFileByBytes(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
            BufferedInputStream in = null;

            try {
                in = new BufferedInputStream(new FileInputStream(file));
                short bufSize = 1024;
                byte[] buffer = new byte[bufSize];
                int len1;
                while (-1 != (len1 = in.read(buffer, 0, bufSize))) {
                    bos.write(buffer, 0, len1);
                }

                byte[] var7 = bos.toByteArray();
                return var7;
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException var14) {
                    var14.printStackTrace();
                }

                bos.close();
            }
        }
    }

    public static String encodeImageToBase64(URL url) throws Exception {
        //将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        //打开链接
        HttpURLConnection conn = null;
        try {
            long startTime = System.currentTimeMillis();
//            log.info("encodeImageToBase64,设置请求方式为");
            conn = (HttpURLConnection) url.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(10 * 1000);
            //通过输入流获取图片数据
//            log.info("encodeImageToBase64,通过输入流获取图片数据。");

            InputStream inStream = conn.getInputStream();
            long connTime = System.currentTimeMillis();
            //得到图片的二进制数据，以二进制封装得到数据，具有通用性
            @Cleanup ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;

            //使用一个输入流从buffer里把数据读取出来
            while ((len = inStream.read(buffer)) != -1) {
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }
            //关闭输入流
            inStream.close();
            byte[] data = outStream.toByteArray();
            log.info("encodeImageToBase64,读取文件完成,图片的路径为:{},数组长度:{}，建立连接耗时：{},总耗时：{}",url.toString(), data.length,connTime-startTime,System.currentTimeMillis()-startTime);

            //对字节数组Base64编码
//            BASE64Encoder encoder = new BASE64Encoder();
//            String base64 = encoder.encode(data);
            String base64 = Base64.getEncoder().encodeToString(data);

            return base64;//返回Base64编码过的字节数组字符串
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception("图片上传失败,请联系客服!");
        }
    }

    public static String encodeImageToJpgBase64(URL url) throws Exception {
        //将图片文件转化为字节数组字符串，并对其进行Base64编码处理
//        System.out.println("图片的路径为:" + url.toString());
        log.info("将图片转码为jpg格式,图片的路径为:" + url.toString());
        //打开链接
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(10 * 1000);
            //通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            //得到图片的二进制数据，以二进制封装得到数据，具有通用性
            @Cleanup ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            //使用一个输入流从buffer里把数据读取出来
            while ((len = inStream.read(buffer)) != -1) {
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }
            //关闭输入流
            inStream.close();
            byte[] data = outStream.toByteArray();

            //转码成jpg图片
            Image imageTookit = Toolkit.getDefaultToolkit().createImage(data);
            BufferedImage cutImage = toBufferedImage(imageTookit);
//            ImageIO.write(cutImage, "jpg", new File("D:/format" + System.currentTimeMillis() + ".jpg"));
            @Cleanup ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(cutImage, "jpg", outputStream);
            data = outputStream.toByteArray();
            //对字节数组Base64编码
//            BASE64Encoder encoder = new BASE64Encoder();
//            return encoder.encode(data);//返回Base64编码过的字节数组字符串
            return Base64.getEncoder().encodeToString(data);//返回Base64编码过的字节数组字符串
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception("图片上传失败,请联系客服!");
        }
    }

    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment
                .getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null),
                    image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }
        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            bimage = new BufferedImage(image.getWidth(null),
                    image.getHeight(null), type);
        }
        // Copy image to buffered image
        Graphics g = bimage.createGraphics();
        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return bimage;
    }

    /**
     * 将多张网络图片进行base64，并将图片url和base64值保存到map里。
     * 图片数据必须按照顺序存放，不然后续接口使用时不知道该取哪一张。所以用list来存。
     *
     * 同一张人脸图片要被拿去做多个操作：优图、微众的人脸注册、对比等，每个操作都需要把图片进行base64转码，网络不稳定时读取网络图片的时间长达5秒及以上。
     * 最优性能：必须保证一张图片只转码一次
     * @param picUrls，以;隔开
     * @return List<HashMap>
     * @throws Exception
     */
    public static List<ImageOfbase64UtilDto> batchEncodeImageToBase64(String picUrls)  {

        try {
            List<ImageOfbase64UtilDto> imagesList = new ArrayList<>();
            List<String> picUrlList = Arrays.asList(picUrls.split(Constants.SEPARATOR_MARK));
            for (String picUrl : picUrlList) {
                ImageOfbase64UtilDto imageOfbase64UtilDto = new ImageOfbase64UtilDto(picUrl, encodeImageToBase64(new URL(picUrl)));
                imagesList.add(imageOfbase64UtilDto);
            }
            return imagesList;
        } catch (Exception e) {
            e.printStackTrace();
            return  new ArrayList<>();
        }

    }

    public static void  main(String[] s){

        List<ImageOfbase64UtilDto> imagesList =FileUtil.batchEncodeImageToBase64("https://picshcos.wkbaobao.com/face/img/799a73df7e7c416381a9400d554fd588.jpg;https://picshcos.wkbaobao.com/face/img/b7b890c10f8a4a338337f914d22f37a2.jpg;https://picshcos.wkbaobao.com/face/img/b7b890c10f8a4a338337f914d22f37a1.jpg");
        log.info(JSONObject.toJSONString(imagesList));
    }


}